﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace SimpleHttpServer.MIME
{
	public enum HttpMimeType
	{
		[MimeDesc("text/plain", "txt", "text")]
		PLAIN,
		[MimeDesc("text/html", "htm", "html")]
		HTML,
		[MimeDesc("text/css", "css")]
		CSS,
		[MimeDesc("image/jpeg", "jpg", "jpeg")]
		JPEG,
		[MimeDesc("image/png", "png")]
		PNG,
		[MimeDesc("image/gif", "gif")]
		GIF,
		[MimeDesc("image/bmp", "bmp")]
		BITMAP,
		[MimeDesc("image/x-icon", "ico")]
		ICON,
		[MimeDesc("image/svg+xml", "svg")]
		SVG,
		[MimeDesc("audio/mpeg", "mp3", "mpg")]
		MPEG,
		[MimeDesc("audio/ogg", "ogg")]
		OGG,
		[MimeDesc("audio/midi", "midi", "mid")]
		MIDI,
		[MimeDesc("audio/wav", "wav")]
		WAV,
		[MimeDesc("audio/webm", "webm")]
		AUDIO_WEBM,
		[MimeDesc("audio/mp4a-latm", "m4a")]
		M4A,
		[MimeDesc("audio/*", "wma", "ape", "flac", "asf", "avi", "tti", "rm", "rmvb", "flv", "mov", "mkv")]
		OTHER_AUDIO,
		[MimeDesc("video/mp4", "mp4")]
		MP4,
		[MimeDesc("application/x-mpegURL", "m3u8")]
		M3U8,
		[MimeDesc("video/MP2T", "ts")]
		TS,
		[MimeDesc("video/webm", "webm")]
		VIDEO_WEBM,
		[MimeDesc("application/json", "json")]
		JSON,
		[MimeDesc("application/xml", "xml")]
		XML,
		[MimeDesc("application/pdf", "pdf")]
		PDF,
		[MimeDesc("application/javascript", "js")]
		JAVASCRIPT,
		[MimeDesc("application/octet-stream")]
		UNKNOW_BYTES,
		[MimeDesc("multipart/form-data")]
		MULTI_PART
	}

	public static class HttpMimeTypeExtension
	{
		/// <summary>
		/// 获取指定mimeType的文字值
		/// </summary>
		/// <param name="type">MimeType</param>
		/// <returns></returns>
		public static string GetMimeType(this HttpMimeType type)
		{
			Type enumType = type.GetType();
			string name = Enum.GetName(enumType, type);
			MimeDescAttribute mimeDesc = enumType.GetField(name).GetCustomAttribute<MimeDescAttribute>();
			return mimeDesc.ContentType;
		}

		/// <summary>
		/// 根据文件扩展名获取对应的mimeType
		/// </summary>
		/// <param name="fileExt">文件扩展名</param>
		/// <returns>Mime类型</returns>
		public static string GetMimeTypeByFileExt(this HttpMimeType mimeType, string fileExt)
		{
			if (string.IsNullOrWhiteSpace(fileExt))
			{
				return HttpMimeType.PLAIN.GetMimeType();
			}

			fileExt = fileExt.ToLower().Trim(' ', '.');
			List<string> mimeTypes = new List<string>();
			foreach (FieldInfo fieldInfo in typeof(HttpMimeType).GetFields())
			{
				var mimeDescAttribute = fieldInfo.GetCustomAttribute<MimeDescAttribute>();
				if (mimeDescAttribute == null) continue;
				if (mimeDescAttribute.FileExtFilter.Any(ext => ext == fileExt))
				{
					return mimeDescAttribute.ContentType;
				}

				if (mimeDescAttribute.AllowPattern && mimeDescAttribute.FileExtFilter.Any(ext => Regex.IsMatch(fileExt, ext)))
				{
					mimeTypes.Add(mimeDescAttribute.ContentType);
				}
			}

			if (mimeTypes.Count > 0)
			{
				return mimeTypes.Last();
			}

			return mimeType.GetMimeType();
		}
	}

	[AttributeUsage(AttributeTargets.Field)]
	public class MimeDescAttribute : Attribute
	{
		public string ContentType { get; }
		public List<string> FileExtFilter { get; }

		public bool AllowPattern { get; }

		public MimeDescAttribute(string contentType, params string[] filters)
		{
			ContentType = contentType;
			FileExtFilter = new List<string>(filters?.Length ?? 0);
			if (filters != null && filters.Length > 0)
			{
				foreach (var filter in filters)
				{
					FileExtFilter.Add(filter);
				}
			}
		}

		public MimeDescAttribute(string contentType, bool allowPattern, params string[] filters) : this(contentType,
			filters)
		{
			AllowPattern = allowPattern;
		}
	}
}
